package com.zengdada.authority.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.zengdada.authority.annotation.SysLog;
import com.zengdada.authority.annotation.SysLogType;
import com.zengdada.authority.config.listener.jobs.TimedTaskJob;
import com.zengdada.authority.config.quartz.JobAndTriggerManager;
import com.zengdada.authority.config.security.intercept.AuthorityUtil;
import com.zengdada.authority.exception.RoutineException;
import com.zengdada.authority.model.*;
import com.zengdada.authority.service.AppDictionaryAuthorityService;
import com.zengdada.authority.service.EnhanceBaseService;
import com.zengdada.authority.service.TimedTaskAuthorityService;
import com.zengdada.authority.service.TimedTaskCronAuthorityService;
import com.zengdada.authority.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: 12614
 * @Contact: 1261438511@qq.com
 * @Date: 2019-03-29 14:20
 * @Description:
 */
@Service
@Slf4j
public class TimedTaskAuthorityServiceImpl extends EnhanceBaseService<TimedTask> implements TimedTaskAuthorityService {

    @Autowired
    JobAndTriggerManager jobAndTriggerManager;

    @Autowired
    AuthorityUtil authorityUtil;

    @Autowired
    @Qualifier("timedTaskCronAuthorityServiceImpl")
    TimedTaskCronAuthorityService timedTaskCronAuthorityService;

    @Autowired
    @Qualifier("appDictionaryAuthorityServiceImpl")
    AppDictionaryAuthorityService appDictionaryAuthorityService;

    @Override
    @SysLog(value = "修改定时任务状态", type = SysLogType.SERVICE)
    public String changeTaskState(String id, String state) {
        String result_temp = "任务'%s' %s 成功", result = "";
        if (StringUtils.isBlank(state)) throw new RoutineException("状态码异常！！");
        TimedTask task = this.selectById(id);
        if (task == null) throw new RoutineException("异常请求！！");
        TimedTaskExtend taskExtend = JSONObject.parseObject(JSONObject.toJSONString(task), TimedTaskExtend.class);
        try {
            Trigger.TriggerState jobState = jobAndTriggerManager.getJobState(taskExtend.getTriggerKey());
            switch (state) {
                case "start":
                    if (jobState == Trigger.TriggerState.NONE) {
                        addJob(taskExtend);
                        result = "启动";
                    }
                    break;
                case "resume":
                    if (jobState == Trigger.TriggerState.PAUSED) {
                        jobAndTriggerManager.resumeJob(taskExtend.getTriggerKey());
                        updateTaskInfo(taskExtend);
                        result = "恢复";
                    }
                    break;
                case "pause":
                    if (jobState == Trigger.TriggerState.NORMAL) {
                        jobAndTriggerManager.pauseJob(taskExtend.getTriggerKey());
                        updateTaskInfo(taskExtend);
                        result = "暂停";
                    }
                    break;
                case "stop":
                    if (jobState == Trigger.TriggerState.NORMAL || jobState == Trigger.TriggerState.PAUSED) {
                        jobAndTriggerManager.deleteJob(taskExtend.getTriggerKey());
                        updateTaskInfo(taskExtend);
                        result = "停止";
                    } else {
                        updateTaskInfo(taskExtend);
                        result = "停止";
                    }
                    break;
            }
        } catch (Exception e) {
            throw new RoutineException(e.getMessage());
        }
        if (result.equals("")) throw new RoutineException("任务状态不匹配，请刷新后再试");
        return String.format(result_temp, task.getName(), result);
    }

    @Override
    public String save(TimedTask timedTask) {
        AppUser user = authorityUtil.getLoginUser();
        timedTask.setModifyTime(new Date());
        timedTask.setModifyUser(user.getId());
        if (StringUtils.isBlank(timedTask.getId())) {
            try {
                CommonUtils.reflectObjectTransString(timedTask, false);
            } catch (Exception e) {
                throw new RoutineException(e.getMessage());
            }
            this.add(timedTask);
        } else {
            this.updateById(timedTask);
        }
        if (timedTask.getState() == 1) {
            try {
                TimedTaskExtend taskExtend = JSONObject.parseObject(JSONObject.toJSONString(timedTask), TimedTaskExtend.class);
                addJob(taskExtend);
            } catch (Exception e) {
                return "任务保存成功，但是没有成功启动：" + e.getMessage();
            }
            return "任务保存成功";
        }
        return "任务保存成功";
    }


    public void addJob(TimedTaskExtend timedTaskExtend) throws Exception {
        TimedTaskCron cron = timedTaskCronAuthorityService.selectById(timedTaskExtend.getCronId());
        addJob(timedTaskExtend, cron);
    }

    public void addJob(TimedTaskExtend timedTaskExtend, TimedTaskCron cron) throws Exception {
        if (cron != null) {
            AppDictionary appDictionary = appDictionaryAuthorityService.selectById(timedTaskExtend.getTaskType());
            if (appDictionary != null && StringUtils.isNoneBlank(appDictionary.getSpareSmall1())) {
                Map<String, Object> jobInfo = jobAndTriggerManager.getJobInfo(timedTaskExtend.getTriggerKey());
                if (jobInfo != null && jobInfo.size() > 1)
                    jobAndTriggerManager.resumeJob(timedTaskExtend.getTriggerKey());
                jobAndTriggerManager.addJob(
                        timedTaskExtend.getExecutionStrategy() == TimedTaskExtend.STRATEGY_MULTITON ? appDictionary.getSpareSmall1() : appDictionary.getSpareSmall2(),
                        timedTaskExtend.getTriggerKey(),
                        cron.getCron(),
                        new HashMap<String, Object>() {{
                            put(TimedTaskJob.TIMED_TASK, timedTaskExtend);
                        }});
                updateTaskInfo(timedTaskExtend);
            } else {
                log.error("定时任务‘{}’启动失败，未找到对应的任务类型或者未设置JOB类", timedTaskExtend.getName());
                throw new RoutineException(String.format("定时任务‘%s’启动失败，未找到对应的任务类型或者未设置JOB类", timedTaskExtend.getName()));
            }
        } else {
            log.error("定时任务‘{}’启动失败，未找到CRON", timedTaskExtend.getName());
            throw new RoutineException(String.format("定时任务‘%s’启动失败，未找到CRON", timedTaskExtend.getName()));
        }
    }

    public void updateTaskInfo(TimedTaskExtend timedTaskExtend) throws SchedulerException {
        Map<String, Object> info = jobAndTriggerManager.getJobInfo(timedTaskExtend.getTriggerKey());

        this.updateById(new TimedTask() {{
            String taskState = String.valueOf(info.getOrDefault("taskState", Trigger.TriggerState.NONE.name()));
            setId(timedTaskExtend.getId());
            setTaskState(taskState);
            setTaskStartTime((Date) info.get("taskStartTime"));
            setTaskPreviousFireTime((Date) info.get("taskPreviousFireTime"));
            setTaskNextFireTime((Date) info.get("taskNextFireTime"));
        }});
    }
}
